package com.xuxueli.applyModules.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @description：HTTPCLIENT封装工具
 */
@Slf4j
public class HttpClientUtilSuccess {

    /**
     * http的get请求
     * @param url
     */
    public static String get(String url) {
        return get(url, "UTF-8");
    }

    /**
     * http的get请求
     * @param url
     */
    public static String get(String url, String charset) {
        return get(url, charset, null);
    }

    public static String get(String url, Map<String, String> headers) {
        return get(url, "UTF-8", headers);
    }

    /**
     * http的get请求，可以设置header头信息
     * @param url
     * @param headers
     * @return
     */
    public static String get(String url, String charset, Map<String, String> headers) {
        HttpGet httpGet = new HttpGet(url);
        if(!CollectionUtils.isEmpty(headers)){
            for(Map.Entry<String, String> item : headers.entrySet()){
                httpGet.setHeader(item.getKey(), item.getValue());
            }
        }
        return executeRequest(httpGet, charset);
    }

    /**
     * http的get请求，增加异步请求头参数
     * @param url
     */
    public static String ajaxGet(String url) {
        return ajaxGet(url, "UTF-8");
    }

    /**
     * http的get请求，增加异步请求头参数
     * @param url
     */
    public static String ajaxGet(String url, String charset) {
        return ajaxGet(url, charset, null);
    }

    public static String ajaxGet(String url, Map<String, String> headers) {
        return ajaxGet(url, "UTF-8", headers);
    }

    /**
     * http的get请求，增加异步请求头参数，可自定义头信息
     * @param url
     * @param headers
     * @return
     */
    public static String ajaxGet(String url, String charset, Map<String, String> headers) {
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("X-Requested-With", "XMLHttpRequest");
        if(!CollectionUtils.isEmpty(headers)){
            for(Map.Entry<String, String> item : headers.entrySet()){
                httpGet.setHeader(item.getKey(), item.getValue());
            }
        }
        return executeRequest(httpGet, charset);
    }

    public static String entityGet(String url, Map<String, String> parameter){
        return entityGet(url,"UTF-8",parameter);
    }


    /**
     * http的get请求，请求参数放在param
     */
    public static String entityGet(String url, String charset, Map<String, String> parameter) {
        HttpGet httpGet = null;
        URIBuilder uriBuilder = null;
        try {
            uriBuilder = new URIBuilder(url);
            for(Map.Entry<String, String> item : parameter.entrySet()) {
                uriBuilder.addParameter(item.getKey(), item.getValue());
            }
            URI uri = uriBuilder.build();
            httpGet = new HttpGet(uri);

        } catch (URISyntaxException e) {
            log.error("this url can not connection");
            e.getMessage();
        }
        return executeRequest(httpGet, charset);
    }

    /**
     * http的post请求，无参POST请求
     */
    public static String post(String url) {
        return post(url, null);
    }


    /**
     * http的post请求，传递map格式参数
     */
/*
    public static String post(String url, Map<String, String> dataMap) {
        return post(url, dataMap);
    }
*/

    /**
     * http的post请求，传递equest参数,header参数
     */
    public static String entityPostAndHeaders(String url, String contentType, Map<String, String> headerMap,Map<String, String> requestMap,Map<String, String> dataMap) {
        HttpPost httpPost = new HttpPost(url);
        if("form".equals(contentType)){
            httpPost.addHeader("content-type", "application/x-www-form-urlencoded;charset=utf-8");
            httpPost.addHeader("Accept", "application/x-www-form-urlencoded");
        }else{
            httpPost.addHeader("content-type", "application/json;charset=utf-8");
            httpPost.addHeader("Accept", "application/json");
        }
        if(null!=headerMap && !headerMap.isEmpty()){
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                httpPost.addHeader(entry.getKey(),entry.getValue());
            }
        }
        try {
            if (dataMap != null){
                if("form".equals(contentType)){
                    List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                    for (Map.Entry<String, String> entry : dataMap.entrySet()) {
                        nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                    }
                    UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nvps, StandardCharsets.UTF_8);
                    httpPost.setEntity(formEntity);
                }else{
                    URIBuilder uriBuilder = new URIBuilder(url);
                    if(null!=requestMap && !requestMap.isEmpty()){
                        List<NameValuePair> parameters = new ArrayList<>();
                        requestMap.forEach((key, value) -> parameters.add(new BasicNameValuePair(key, value)));
                        uriBuilder.setParameters(parameters);
                    }
                    HttpEntity httpEntity = new StringEntity(JSONObject.parseObject(JSON.toJSONString(dataMap)).toString(),"utf-8");
                    httpPost.setEntity(httpEntity);
                    httpPost.setURI(uriBuilder.build());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return executeRequest(httpPost);
    }

    /**
     * http的post请求，传递map格式参数
     */
    public static String entityPost(String url, Map<String, String> dataMap) {
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("content-type", "application/json;charset=utf-8");
        httpPost.addHeader("Accept", "application/json");

        try {
            if (dataMap != null){
                URIBuilder uriBuilder = new URIBuilder(url);
                HttpEntity httpEntity = new StringEntity(JSONObject.parseObject(JSON.toJSONString(dataMap)).toString(),"utf-8");
                httpPost.setEntity(httpEntity);
                httpPost.setURI(uriBuilder.build());

            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return executeRequest(httpPost);
    }

    public static String multiEntityPost(String url, Map<String, String> dataMap,Map<String, String> headerMap) {
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("content-type", "application/x-www-form-urlencoded;charset=utf-8");
        httpPost.addHeader("Accept", "application/x-www-form-urlencoded");
        if(null!=headerMap && !headerMap.isEmpty()){
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                httpPost.addHeader(entry.getKey(),entry.getValue());
            }
        }
        try {
            if (dataMap != null){
                List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                for (Map.Entry<String, String> entry : dataMap.entrySet()) {
                    nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nvps, StandardCharsets.UTF_8);
                httpPost.setEntity(formEntity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return executeRequest(httpPost);
    }

    /**
     * 参数
     * @param url
     * @param pairList
     * @param headerMap
     * @return
     */
    public static String multiEntityParaPost(String url, List<NameValuePair> pairList, Map<String, String> headerMap) {
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("content-type", "application/x-www-form-urlencoded;charset=utf-8");
        httpPost.addHeader("Accept", "application/x-www-form-urlencoded");
        if(null!=headerMap && !headerMap.isEmpty()){
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                httpPost.addHeader(entry.getKey(),entry.getValue());
            }
        }
        try {
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(pairList, StandardCharsets.UTF_8);
            httpPost.setEntity(formEntity);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return executeRequest(httpPost);
    }

    /**
     * 参数
     * @param url
     * @param dataMap
     * @param headerMap
     * @return
     */
    public static String multiEntityObjectPost(String url, Map<String, Object> dataMap,Map<String, String> headerMap) {
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("content-type", "application/x-www-form-urlencoded;charset=utf-8");
        httpPost.addHeader("Accept", "application/x-www-form-urlencoded");
        if(null!=headerMap && !headerMap.isEmpty()){
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                httpPost.addHeader(entry.getKey(),entry.getValue());
            }
        }
        try {
            if (dataMap != null){
                List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
                    nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue().toString()));
                }
                UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nvps, StandardCharsets.UTF_8);
                httpPost.setEntity(formEntity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return executeRequest(httpPost);
    }

    public static String multiEntityPut(String url, Map<String, String> dataMap,Map<String, String> headerMap) {
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("content-type", "application/x-www-form-urlencoded;charset=utf-8");
        httpPost.addHeader("Accept", "application/x-www-form-urlencoded");
        if(null!=headerMap && !headerMap.isEmpty()){
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                httpPost.addHeader(entry.getKey(),entry.getValue());
            }
        }
        try {
            if (dataMap != null){
                List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                for (Map.Entry<String, String> entry : dataMap.entrySet()) {
                    nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nvps, StandardCharsets.UTF_8);
                httpPost.setEntity(formEntity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return executeRequest(httpPost);
    }

    public static String multiEntityPatch(String url, Map<String, String> dataMap,Map<String, String> headerMap) {
        HttpPatch httpPatch = new HttpPatch(url);
        httpPatch.addHeader("content-type", "application/x-www-form-urlencoded;charset=utf-8");
        httpPatch.addHeader("Accept", "application/x-www-form-urlencoded");
        if(null!=headerMap && !headerMap.isEmpty()){
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                httpPatch.addHeader(entry.getKey(),entry.getValue());
            }
        }
        try {
            if (dataMap != null){
                List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                for (Map.Entry<String, String> entry : dataMap.entrySet()) {
                    nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nvps, StandardCharsets.UTF_8);
                httpPatch.setEntity(formEntity);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return executeRequest(httpPatch);
    }

    /**
     * http的post请求，传递map格式参数
     */
    public static String post(String url, Map<String, String> dataMap) {
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("content-type", "application/json;charset=utf-8");
        httpPost.addHeader("Accept", "application/json");
        try {
            if (dataMap != null){
                List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                for (Map.Entry<String, String> entry : dataMap.entrySet()) {
                    nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                URIBuilder uriBuilder = new URIBuilder(url);
                List<NameValuePair> parameters = new ArrayList<>();
                dataMap.forEach((key, value) -> parameters.add(new BasicNameValuePair(key, value)));
                uriBuilder.setParameters(parameters);
                httpPost.setURI(uriBuilder.build());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return executeRequest(httpPost);
    }

    /**
     * http的post请求，增加异步请求头参数，传递map格式参数
     */
    public static String ajaxPost(String url, Map<String, String> dataMap) {
        return ajaxPost(url, dataMap, "UTF-8");
    }

    /**
     * http的post请求，增加异步请求头参数，传递map格式参数
     */
    public static String ajaxPost(String url, Map<String, String> dataMap, String charset) {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
        try {
            if (dataMap != null){
                List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                for (Map.Entry<String, String> entry : dataMap.entrySet()) {
                    nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nvps, charset);
                formEntity.setContentEncoding(charset);
                httpPost.setEntity(formEntity);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return executeRequest(httpPost, charset);
    }

    /**
     * http的post请求，增加异步请求头参数，传递json格式参数
     */
    public static String ajaxPostJson(String url, String jsonString) {
        return ajaxPostJson(url, jsonString, "UTF-8");
    }

    /**
     * http的post请求，增加异步请求头参数，传递json格式参数
     */
    public static String ajaxPostJson(String url, String jsonString, String charset) {
        return ajaxPostJson(url, jsonString, charset, null);
    }

    public static String ajaxPostJson(String url, String jsonString, Map<String, String> headers) {
        return ajaxPostJson(url, jsonString, "UTF-8", headers);
    }

    /**
     * http的post请求，增加异步请求头参数，传递json格式参数
     * @param url
     * @param jsonString
     * @param charset
     * @param headers
     * @return
     */
    public static String ajaxPostJson(String url, String jsonString, String charset, Map<String, String> headers) {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
        if(!CollectionUtils.isEmpty(headers)){
            for(Map.Entry<String, String> item : headers.entrySet()){
                httpPost.setHeader(item.getKey(), item.getValue());
            }
        }

        StringEntity stringEntity = new StringEntity(jsonString, charset);// 解决中文乱码问题
        stringEntity.setContentEncoding(charset);
        stringEntity.setContentType("application/json");
        httpPost.setEntity(stringEntity);

        return executeRequest(httpPost, charset);
    }

    /**
     * 执行一个http请求，传递HttpGet或HttpPost参数
     */
    public static String executeRequest(HttpUriRequest httpRequest) {
        return executeRequest(httpRequest, "UTF-8");
    }

    /**
     * 执行一个http请求，传递HttpGet或HttpPost参数
     */
    public static String executeRequest(HttpUriRequest httpRequest, String charset) {
        CloseableHttpClient httpclient;
        if (StringUtils.containsIgnoreCase(httpRequest.getURI().getScheme(),"https:")){
            httpclient = createSSLInsecureClient();
        }else{
            httpclient = HttpClients.createDefault();
        }
        String result = "";
        try {
            try {
                CloseableHttpResponse response = httpclient.execute(httpRequest);
                HttpEntity entity = null;
                try {
                    entity = response.getEntity();
                    if (null != entity) {
                        result = EntityUtils.toString(entity, charset);
                    }
                } finally {
                    EntityUtils.consume(entity);
                    response.close();
                }
            } finally {
                httpclient.close();
            }
        }catch(IOException ex){
            ex.printStackTrace();
        }
        return result;
    }

    /**
     * 创建 SSL连接
     */
    public static CloseableHttpClient createSSLInsecureClient() {
        try {
            SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(new TrustStrategy() {
                @Override
                public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }).build();
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
            return HttpClients.custom().setSSLSocketFactory(sslsf).build();
        } catch (GeneralSecurityException ex) {
            throw new RuntimeException(ex);
        }
    }

    public static String delete(String url,Map<String, String> headerMap) {
        HttpDelete httpDelete = new HttpDelete(url);
        if(null!=headerMap && !headerMap.isEmpty()){
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                httpDelete.addHeader(entry.getKey(),entry.getValue());
            }
        }
        httpDelete.addHeader("content-type", "application/json;charset=utf-8");
        httpDelete.addHeader("Accept", "application/json");
        return executeRequest(httpDelete, "UTF-8");
    }

    /**
     * http的post请求，传递map格式参数
     */
    public static String releaseDelete(String url, Map<String, String> dataMap) {
        return deleteJson(url, dataMap, "UTF-8");
    }

    public static String deleteJson(String url, Map<String, String> dataMap, String charset) {
        HttpDelete httpDelete = new HttpDelete(url);
        httpDelete.addHeader("content-type", "application/json;charset=utf-8");
        httpDelete.addHeader("Accept", "application/json");
        try {
            if (dataMap != null){
                List<NameValuePair> nvps = new ArrayList<NameValuePair>();
                for (Map.Entry<String, String> entry : dataMap.entrySet()) {
                    nvps.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
                }
                URIBuilder uriBuilder = new URIBuilder(url);
                List<NameValuePair> parameters = new ArrayList<>();
                dataMap.forEach((key, value) -> parameters.add(new BasicNameValuePair(key, value)));
                uriBuilder.setParameters(parameters);
                httpDelete.setURI(uriBuilder.build());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return executeRequest(httpDelete, charset);
    }
}
